import * as THREE from "../../../modules/three/three.module.js";
import BlockingMesh from '../lib/gadget/BlockingMesh.js';
import Blocking from '../model/Blocking.js';
import PluginBase from './PluginBase.js';
import {MouseButton} from "../lib/CommonConsts.js";
import {eventScaleChanged} from "../lib/gadget/ScaleControl.js";
import {eventDraggingChanged} from "../lib/gadget/TransformRotateControl.js";
import UndoType from "../scene/undo/UndoType.js";

export default class BlockingMeshPlugin extends PluginBase {
  /**
   * @type {World3d}
   */
  world3d;
  /**
   * @type {BlockingMesh|null}
   */
  movingBlocking;

  constructor(world3d) {
    super();
    this.world3d = world3d;
    const transformControl = world3d.transformRotateControl;
    const scaleControl = world3d.scaleControl;
    transformControl.addEventListener(eventDraggingChanged.type, (event) => {
      if (!(transformControl.object instanceof BlockingMesh) || event.value) {
        return;
      }
      const obj = transformControl.object;
      const ctx = {
        blockingMesh: obj,
        position0: new THREE.Vector3().copy(obj.positionOld),
        position: new THREE.Vector3().copy(obj.position),
        rotation0: new THREE.Euler().copy(obj.rotationOld),
        rotation: new THREE.Euler().copy(obj.rotation),
      };
      world3d.editRecord.addAction(UndoType.transformBlocking, ctx);
    });

    scaleControl.addEventListener(eventScaleChanged.type, (event) => {
      if (!(scaleControl.object instanceof BlockingMesh) || event.value) {
        return;
      }
      const obj = scaleControl.object;
      const ctx = {
        blockingMesh: obj,
        position0: new THREE.Vector3().copy(obj.positionOld),
        position: new THREE.Vector3().copy(obj.position),
        scale0: new THREE.Vector3().copy(obj.scaleOld),
        scale: new THREE.Vector3().copy(obj.scale),
        scaleControl: scaleControl,
      };
      world3d.editRecord.addAction(UndoType.transformBlocking, ctx);
    });
  }

  dropdownBlocking(event) {
    if (event.button === MouseButton.right && this.movingBlocking) {
      const index = this.world3d.store.blockings.indexOf(this.movingBlocking);
      if (index >= 0) {
        this.world3d.store.blockings.splice(index, 1);
      }
      this.movingBlocking.removeFromParent();
    } else {
      if (this.movingBlocking) {
        // 新增的模型 放置好了位置
        const ctx = {
          blockingMesh: this.movingBlocking,
          arr: this.world3d.store.blockings,
          scene: this.world3d.scene,
        };
        this.world3d.editRecord.addAction(UndoType.addBlocking, ctx);
      }
    }
    this.movingBlocking = null;
  }

  pointerMove(event) {
    const world3d = this.world3d;
    const store = this.world3d.store;
    const raycaster = world3d.mouseRaycaster;
    if (store.stateAddingBlocking && !this.movingBlocking) {
      const mesh = new BlockingMesh().initBlocking(new Blocking());
      world3d.scene.add(mesh);
      store.blockings.push(mesh);
      this.movingBlocking = mesh;
    }
    if (!this.movingBlocking) {
      return;
    }
    const tileIntersects = raycaster.intersectObject(world3d.tiles.group, true);
    if (tileIntersects.length) {
      this.movingBlocking.position.copy(tileIntersects[0].point);
    }
  }
  pointerUpMoved(event) {
    this.dropdownBlocking(event);
  }
  pointerUpUnmoved(event) {
    this.dropdownBlocking(event);
    const world3d = this.world3d;
    const store = this.world3d.store;
    if (event.button === MouseButton.right) {
      if (store.stateAddingBlocking) {
        store.freeState();
      }
      return;
    }

    if (!store.stateFree) {
      return;
    }
    const raycaster = world3d.mouseRaycaster;
    // console.log('blockingMesh pointerUpUnmoved, cam name: ', raycaster.camera.name);
    const itemIntersects = raycaster.intersectObjects(store.blockings, false);
    if (itemIntersects.length) {
      // 选中已经存在的障碍物
      const blockingMesh = itemIntersects[0].object;
      blockingMesh.backupTransform();
      world3d.attachObject(blockingMesh);
      // console.log('attached to blockingMesh');
    } else {
      const selectBlocking = world3d.getAttachingObject();
      if (selectBlocking && selectBlocking instanceof BlockingMesh) {
        selectBlocking.updateVO();
        world3d.detachObject();
      }
    }
  }
}
